import com.adobe.crypto.MD5;
import com.adobe.utils.IntUtil;
import com.limetalks.data.Stream;
import com.limetalks.data.User;
import com.limetalks.events.LimeEvent;
import com.limetalks.logic.Encryption;

import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.StatusEvent;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.Responder;
import flash.ui.Keyboard;

import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.events.ListEvent;

private var stream:String;
private var mySelf:String;

//network properties
//private var connection:NetConnection;
private var inStream:NetStream;
private var outStream:NetStream;

//device properties
private var camera:Camera;
private var microphone:Microphone;

//video properties
private var inVideo:Video;
private var outVideo:Video;

//wrapper flex properties
//private var inVideoWrapper:UIComponent;
//private var outVideoWrapper:UIComponent;

private var streamListDataProvider:ArrayCollection = new ArrayCollection();

public function onCreationComplete(event:FlexEvent) : void {
	// setup connection code
	/*connection = new NetConnection();
	connection.addEventListener(NetStatusEvent.NET_STATUS, onConnectionNetStatus);
	connection.client = this;	*/
	limeTalksChat.addEventListener(LimeEvent.CONNECTION, onConnectionRise);
	limeTalksChat.addEventListener(LimeEvent.LOGIN, onLogin);
	limeTalksChat.addEventListener(LimeEvent.LOGIN_ERROR, onLoginError);
	limeTalksChat.addEventListener(LimeEvent.LOGOUT, onLogout);
	limeTalksChat.addEventListener(LimeEvent.STREAM_START, onStreamStart);
	limeTalksChat.addEventListener(LimeEvent.STREAM_STOP, onStreamStop);
	limeTalksChat.addEventListener(LimeEvent.STREAM_JOIN, onStreamJoin);
	limeTalksChat.addEventListener(LimeEvent.STREAM_LEAVE, onStreamLeave);
	limeTalksChat.addEventListener(LimeEvent.STREAM_UPDATE, onStreamUpdate);
}

public function onConnectionNetStatus(event:NetStatusEvent) : void {
	log(event.info.code);
//	connection.call("getStreams_Server", new Responder(onStreamListResult, onError));
	// did we successfully connect
	if(event.info.code == "NetConnection.Connect.Success") {
		//Alert.show("Successful Connection", "Information");
		//connectionStatusLabel.text = "Connected";
		setupOutgoingDevices();
	}/* else if(event.info.code == "NetConnection.Connect.Closed"){
		connectionStatusLabel.text = "Disconnected";
	} else {
		connectionStatusLabel.text = "Failed to connect";
		//Alert.show("Unsuccessful Connection", "Information");
	}*/
}

private function setupOutgoingDevices() : void {
	//setup outgoing devices
	camera = Camera.getCamera();
//	camera.addEventListener(StatusEvent.STATUS, cameraStatusHandler);
	microphone = Microphone.getMicrophone();	
	
}

/*function cameraStatusHandler(event:StatusEvent):void
{
	if (camera.muted)
	{
		trace("Unable to connect to active camera.");
	}
	else
	{
		// Resize Video object to match camera settings and 
		// add the video to the display list.
		outSipmeVideo.width = camera.width;
		outSipmeVideo.height = camera.height;
	}
	// Remove the status event listener.
	camera.removeEventListener(StatusEvent.STATUS, cameraStatusHandler);
}*/

private function setupIncominStream() : void {
	//setup incoming stream
	inStream = new NetStream(limeTalksChat.connection);
	inStream.play("stream");
	
	//setup incoming video and attach incoming stream
	//	inVideo = new Video();
	//	inVideo.attachNetStream(inStream);
	inSipmeVideo.attachNetStream(inStream);
}

private function stopIncominStream() : void {
	inStream.close();
	inSipmeVideo.reset();
}

private function setupOutgoingStream() : void {
	//setup outgoing stream
	outStream = new NetStream(limeTalksChat.connection);
	if(outputCameraCheckBox.selected){
		outStream.attachCamera(camera);
		outSipmeVideo.attachCamera(camera);
	}
	if(outputMicrophoneCheckBox.selected){
		outStream.attachAudio(microphone);	
	}	
	outStream.publish("stream");
	
	//setup outgoing video and attach outgoing devices
	//	outVideo = new Video();
	//	outVideo.attachCamera(camera);	
}

private function stopOutgoingStream() : void {
	outStream.close();
	outSipmeVideo.reset();	
}

protected function button1_clickHandler(event:MouseEvent):void
{
	//Alert.show("Sending request to the server...");
//	connection.call("RemoteClass.sayHello", new Responder(onHelloResult,onError), "Max");
}

protected function userButton_clickHandler(event:MouseEvent):void
{
	//Alert.show("Sending request to the server...");
//	connection.call("RemoteClass.getUser", new Responder(onUserResult, onError), "Max");
}

protected function userDbButton_clickHandler(event:MouseEvent):void
{
	//Alert.show("Sending request to the server...");
//	connection.call("getDbUser", new Responder(onUserResult, onError), email.text, Encryption.encrypt(password.text, Encryption.CRYPTIT_MD5, true));
}

protected function usersButton_clickHandler(event:MouseEvent):void
{
	//Alert.show("Sending request to the server...");
//	var names:Array = new Array("Max", "Alex");
//	connection.call("RemoteClass.getUsers", new Responder(onUsersResult, onError), names);
}

protected function onHelloResult(result:Object):void{
	Alert.show("RPC responce: " + result);
}

protected function onUserResult(result:User):void{
	Alert.show("RPC responce: " + result.name);
}

protected function onStreamListResult(result:Array):void{
	//Alert.show("Stream List RPC responce: " + result.length);
	streamsDP.source = result;
}

protected function onUsersResult(result:Array):void{
	Alert.show("RPC responce: " + result[0].name + ", " + result[1].name);
}

protected function onError(error:Object):void{
	Alert.show("RPC failed: " + error);
}

protected function connectButton_clickHandler(event:MouseEvent):void
{	
	log("Connecting...");
	limeTalksChat.connect(connectionUrlInput.text);	
}	

protected function disconnectButton_clickHandler(event:MouseEvent):void
{
	limeTalksChat.disconnect();
}

protected function createStreamButton_clickHandler(event:MouseEvent):void
{
	startStream(createStreamInput.text);
}

protected function removeStreamButton_clickHandler(event:MouseEvent):void
{
	stopStream(createStreamInput.text);
}

protected function joinStreamButton_clickHandler(event:MouseEvent):void
{
	joinStream(joinStreamInput.text);
}

protected function leaveStreamButton_clickHandler(event:MouseEvent):void
{
	leaveStream(joinStreamInput.text);
}

private function startStream(name:String):void
{				
//	connection.call("startStream_Server", new Responder(startStreamResult), name);
	limeTalksChat.startStream(name);
}

private function startStreamResult(ok:Boolean):void
{
	log("Stream started: " + ok);
}


private function stopStream(name:String):void
{				
//	connection.call("stopStream_Server", new Responder(stopStreamResult), name);
	limeTalksChat.leaveStream(name);
}

private function stopStreamResult():void
{
	log("Stream stopped");
}

public function onStreamStarted_Client(stream:Stream):void
{
	log("Stream started: " + stream.name);
	streamsDP.addItem(stream);
}

public function onStreamStopped_Client(stream:Stream):void
{
	log("Stream stopped: " + stream.name);
	streamsDP.removeItemAt(streamsDP.getItemIndex(stream));
}

public function onStreamUpdated_Client(stream:Stream):void
{
	log("Stream updated: name=" + stream.name + "; usersCount=" + stream.users.length);	
	for each (var item:Object in streamsDP) 
	{
		if(item.name == stream.name)
		{
			item.name = stream.name;
			item.users = stream.users;
			streamsDP.refresh();
		}
	}
}

public function onUserStreamJoin_Client(user:User, stream:Stream):void
{
	log("User " + user.id + " has joined the stream '" + stream.name + "'");
}

public function onUserStreamLeft_Client(user:User, stream:Stream):void
{
	log("User " + user.id + " has left the stream '" + stream.name + "'");
}

protected function sendPublicButton_clickHandler(event:MouseEvent):void
{
	sendPublicMessage(txtMsgInput.text);
	txtMsgInput.enabled = false;
}

protected function sendStreamButton_clickHandler(event:MouseEvent):void
{
	sendStreamMessage(txtMsgInput.text);
	txtMsgInput.enabled = false;
}

protected function txtMsgInput_keyUpHandler(event:KeyboardEvent):void
{
	if(event.keyCode == Keyboard.ENTER){
		sendPublicMessage(txtMsgInput.text);
		txtMsgInput.enabled = false;
	}
}

private function sendPublicMessage(message:String):void
{
//	connection.call("sendPublicMessage_Server", new Responder(OnSendMessageResult), msg);
	limeTalksChat.sendPublicMessage(message);
}

private function sendStreamMessage(message:String):void
{
	//	connection.call("sendPublicMessage_Server", new Responder(OnSendMessageResult), msg);
	limeTalksChat.sendStreamMessage(message);
}

private function OnSendMessageResult(result:Boolean):void
{
	trace("SendPublicMessageResult: " + result);
	txtMsgInput.text = "";
	txtMsgInput.enabled = true;
	txtMsgInput.setFocus();
}

public function streamsLabelFunc(item:Stream):String {
	var streamName:String = item.name.replace("rtmp://localhost/LimeTalksRed5/", "");
	return streamName + " (" + item.users.length + ")"; 
}

public function streamList_itemClickHandler(event:Event):void
{	
	//				chatTextArea.text += event.currentTarget.selectedItem.name + "\n";
	joinStream(event.currentTarget.selectedItem.name);
}

public function userList_itemClickHandler(event:Event):void {
	Alert.show("New user selected: ");
}

public function joinStream(streamName:String):void
{
//	connection.call("joinStream_Server", new Responder(joinStream_Client), streamName);
	limeTalksChat.joinStream(streamName);
}

public function leaveStream(streamName:String):void
{
//	connection.call("leaveStream_Server", new Responder(leaveStream_Client), streamName);
	limeTalksChat.leaveStream(streamName);
}

protected function publishStreamCheckBox_clickHandler(event:MouseEvent):void
{
	if(publishStreamCheckBox.selected){
		setupOutgoingStream();
	}else{
		stopOutgoingStream();
	}
}

protected function receiveStreamCheckBox_clickHandler(event:MouseEvent):void
{
	if(receiveStreamCheckBox.selected){
		setupIncominStream();
	}else{
		stopIncominStream();
	}
}

private function onConnectionRise(event:LimeEvent):void {
	if(event.params.success) {
		log("Connection Success");
		
		/*if(stream.master.id == mySelf.id) {
			setupOutgoingDevices();
			setupOutgoingStream();		
		} else {
			setupIncominStream();
		}*/
		
	} else {
		log("Connection Failed");
	}
}

private function onLogin(event:LimeEvent) : void {
	log("User '" + event.params.user + "' login");
	mySelf = event.params.user;
	//limeTalks.startAndJoinStream(streamId);	
}

private function onLoginError(event:LimeEvent) : void {	
	log("Login error");
}

private function onLogout(event:LimeEvent) : void {	
	log("Logout");
}

private function onStreamStart(event:LimeEvent) : void 
{
	log("Stream started: " + event.params.stream);
}

private function onStreamStop(event:LimeEvent) : void 
{
	log("Stream stopped: " + event.params.stream);
}

private function onStreamJoin(event:LimeEvent) : void 
{
	log("User '" + event.params.user + "' has joined the stream '" + event.params.stream + "'");
}

private function onStreamLeave(event:LimeEvent) : void 
{
	log("User '" + event.params.user + "' has left the stream '" + event.params.stream + "'");
}

private function onStreamUpdate(event:LimeEvent) : void 
{
	log("Stream '" + event.params.stream + "' has been updated");
}

private function log(msg:String){
	//chatTextArea.setStyle("color", color);
	chatTextArea.text += msg + "\n";
}